package com.frontop.terminal.gangedsocket.core;

import com.alibaba.fastjson.JSON;
import com.frontop.terminal.entity.Message;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.EOFException;
import java.io.IOException;
import java.net.Socket;
import java.net.SocketException;
import java.util.Objects;

import static com.frontop.terminal.vlcjplayer.Application.application;

/**
 * <p>
 *
 * </p>
 *
 * @author :CCC
 * @since :2021-10-14
 **/
public class PlayGangedService implements Runnable {

    private final Socket socket;
    /**
     * 心跳
     */
    private Integer heartbeatTime;
    /**
     * 心跳中允许无响应次数
     */
    private Integer numberOfConnection;
    /**
     * 停止线程标志
     */
    private boolean release;
    private DataInputStream inputStream;
    private DataOutputStream outputStream;

    public PlayGangedService(Socket socket) {
        this.socket = socket;
        try {
            socket.setKeepAlive(true);
            this.inputStream = new DataInputStream(socket.getInputStream());
            this.outputStream = new DataOutputStream(socket.getOutputStream());
        } catch (IOException e) {
            e.printStackTrace();
        }
        release = true;
    }

    @Override
    public void run() {
        try {
            while (release) {
                if (!socket.isClosed()) {
                    String msg = inputStream.readUTF();
                    System.out.println("[播放联动socket服务端]收到信息:" + msg);

                    //收到客户端关闭连接通知
                    if (PlayGangedServiceSocket.COLSE.equals(msg)) {
                        release();
                    } else if (Heartbeat.HEARTBEAT_RESPONSE.equals(msg)) {
                        //响应心跳
                        heartbeatTime = 0;
                        numberOfConnection = Heartbeat.heartbeatTime + 1;
                    } else if (msg.equals(DelayOffset.TIMELINE)) {
                        //获取时间轴
                        //视频在播放的话
                        if (application().mediaPlayer().status().isPlaying()) {
                            //获取时间轴
                            long timeline = application().mediaPlayer().status().time();
                            Message message = new Message();
                            message.setType(DelayOffset.TIMELINE);
                            message.setCommand(String.valueOf(timeline));
                            send(JSON.toJSONString(message));
                        }
                    } else {
                        Message message = JSON.parseObject(msg, Message.class);
                        //客户端延迟补偿进入准备状态
                        if (message.getType().equals(DelayOffset.DELAY)) {
                            send(msg);
                        }
                    }
                }
            }
        } catch (EOFException e) {
            System.out.println("[播放联动socket服务端]数据读取到了末尾");
        } catch (SocketException e) {
            System.out.println("[播放联动socket服务端]Socket closed");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void send(String msg) {
        if (!this.socket.isClosed()) {
            try {
                this.outputStream.writeUTF(msg);
                this.outputStream.flush();
            } catch (SocketException e) {
                System.out.println("Connection reset by peer: socket write error");
            } catch (IOException e) {
                e.printStackTrace();
            } catch (Exception e) {
                e.printStackTrace();
            }
        } else {
            System.out.println("[播放联动socket服务端]无法发送信息,连接已经关闭");
        }
    }

    public void release() {
        System.out.println("[播放联动socket服务端]主动关闭连接并释放资源");
        this.release = false;
        try {
            if (Objects.nonNull(socket)) {
                this.socket.close();
                this.inputStream.close();
                this.outputStream.close();

                if (PlayGangedServiceSocket.clients.remove(this)) {
                    System.out.println("[播放联动socket服务端]已将该连接在列表中移除");
                }

            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public Integer getHeartbeatTime() {
        return heartbeatTime;
    }


    public Integer getNumberOfConnection() {
        return numberOfConnection;
    }

    public void setNumberOfConnection(Integer numberOfConnection) {
        this.numberOfConnection = numberOfConnection;
    }
}
